package org.example.liuy.service.session;

import lombok.Getter;

/**
 * 会话信息类 - 使用不可变对象模式和建造者模式
 * 表示一个用户会话的所有相关信息
 */
@Getter
public class SessionInfo {
    private final String sessionKey;
    private final Integer customerId;
    private final long creationTime;
    private final long lastAccessTime;
    private final long expirationTime;
    private final String userAgent;
    private final String clientIp;
    private final int accessCount;

    // 私有构造函数，强制使用建造者
    private SessionInfo(Builder builder) {
        this.sessionKey = builder.sessionKey;
        this.customerId = builder.customerId;
        this.creationTime = builder.creationTime;
        this.lastAccessTime = builder.lastAccessTime;
        this.expirationTime = builder.expirationTime;
        this.userAgent = builder.userAgent;
        this.clientIp = builder.clientIp;
        this.accessCount = builder.accessCount;
    }
    /**
     * 更新访问时间（返回新的SessionInfo对象，保持不可变性）
     */
    public SessionInfo updateAccessTime() {
        return new Builder(this.sessionKey, this.customerId)
                .userAgent(this.userAgent)
                .clientIp(this.clientIp)
                .accessCount(this.accessCount + 1)
                .creationTime(this.creationTime)
                .expirationTime(this.expirationTime)
                .lastAccessTime(System.currentTimeMillis())
                .build();
    }

    /**
     * 延长会话有效期
     */
    public SessionInfo extendValidity(long additionalMillis) {
        return new Builder(this.sessionKey, this.customerId)
                .userAgent(this.userAgent)
                .clientIp(this.clientIp)
                .accessCount(this.accessCount)
                .creationTime(this.creationTime)
                .lastAccessTime(System.currentTimeMillis())
                .expirationTime(this.expirationTime + additionalMillis)
                .build();
    }    /**
     * 建造者模式
     */
    public static class Builder {
        private final String sessionKey;
        private final Integer customerId;
        private long creationTime;
        private long lastAccessTime;
        private long expirationTime;
        private String userAgent = "Unknown";
        private String clientIp = "0.0.0.0";
        private int accessCount = 0;

        public Builder(String sessionKey, Integer customerId) {
            this.sessionKey = sessionKey;
            this.customerId = customerId;
            this.creationTime = System.currentTimeMillis();
            this.lastAccessTime = this.creationTime;
            // 默认会话有效期10分钟 -
            this.expirationTime = this.creationTime + 10 * 60 * 1000;
        }

        public Builder userAgent(String userAgent) {
            this.userAgent = userAgent;
            return this;
        }

        public Builder clientIp(String clientIp) {
            this.clientIp = clientIp;
            return this;
        }

        public Builder accessCount(int accessCount) {
            this.accessCount = accessCount;
            return this;
        }

        public Builder expirationTime(long expirationTime) {
            this.expirationTime = expirationTime;
            return this;
        }

        public SessionInfo build() {
            return new SessionInfo(this);
        }

        public Builder creationTime(long creationTime) {
            this.creationTime = creationTime;
            return this;
        }

        public Builder lastAccessTime(long l) {
            this.lastAccessTime = l;
            return this;
        }
    }

    /**
     * 创建新会话的工厂方法
     */
    public static SessionInfo createNew(String sessionKey, Integer customerId) {
        return new Builder(sessionKey, customerId).build();
    }

    /**
     * 创建带客户端信息的会话
     */
    public static SessionInfo createWithClientInfo(String sessionKey, Integer customerId,
                                                   String userAgent, String clientIp) {
        return new Builder(sessionKey, customerId)
                .userAgent(userAgent)
                .clientIp(clientIp)
                .build();
    }



    /**
     * 检查会话是否过期
     */
    public boolean isExpired() {
        return System.currentTimeMillis() > expirationTime;
    }

    /**
     * 获取剩余有效时间（毫秒）
     */
    public long getRemainingTime() {
        return Math.max(0, expirationTime - System.currentTimeMillis());
    }

    /**
     * 获取会话年龄（毫秒）
     */
    public long getAge() {
        return System.currentTimeMillis() - creationTime;
    }

    /**
     * 检查会话是否即将过期（在1分钟内过期）
     */
    public boolean isAboutToExpire() {
        return getRemainingTime() < 60 * 1000;
    }

    /**
     * 获取会话活跃度（访问次数/分钟）
     */
    public double getActivityRate() {
        long ageMinutes = getAge() / (60 * 1000);
        return ageMinutes > 0 ? (double) accessCount / ageMinutes : accessCount;
    }

    @Override
    public String toString() {
        return String.format("SessionInfo{sessionKey=%s, customerId=%s, creationTime=%d, " +
                        "lastAccessTime=%d, expirationTime=%d, accessCount=%d, userAgent=%s, clientIp=%s}",
                sessionKey, customerId, creationTime, lastAccessTime, expirationTime,
                accessCount, userAgent, clientIp);
    }

    /**
     * 转换为JSON格式
     */
    public String toJson() {
        return String.format("{\"sessionKey\":\"%s\",\"customerId\":\"%s\",\"creationTime\":%d," +
                        "\"lastAccessTime\":%d,\"expirationTime\":%d,\"accessCount\":%d," +
                        "\"userAgent\":\"%s\",\"clientIp\":\"%s\",\"remainingTime\":%d,\"isExpired\":%b}",
                sessionKey, customerId, creationTime, lastAccessTime, expirationTime,
                accessCount, escapeJson(userAgent), escapeJson(clientIp),
                getRemainingTime(), isExpired());
    }

    /**
     * 转换为CSV格式
     */
    public String toCsv() {
        return String.format("%s,%s,%d,%d,%d,%d,%s,%s,%d,%b",
                sessionKey, customerId, creationTime, lastAccessTime, expirationTime,
                accessCount, escapeCsv(userAgent), escapeCsv(clientIp),
                getRemainingTime(), isExpired());
    }

    /**
     * 获取CSV头信息
     */
    public static String getCsvHeader() {
        return "sessionKey,customerId,creationTime,lastAccessTime,expirationTime," +
                "accessCount,userAgent,clientIp,remainingTime,isExpired";
    }

    // JSON转义工具方法
    private String escapeJson(String value) {
        return value.replace("\"", "\\\"")
                .replace("\\", "\\\\")
                .replace("\b", "\\b")
                .replace("\f", "\\f")
                .replace("\n", "\\n")
                .replace("\r", "\\r")
                .replace("\t", "\\t");
    }

    // CSV转义工具方法
    private String escapeCsv(String value) {
        if (value.contains(",") || value.contains("\"") || value.contains("\n")) {
            return "\"" + value.replace("\"", "\"\"") + "\"";
        }
        return value;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        SessionInfo that = (SessionInfo) o;
        return sessionKey.equals(that.sessionKey);
    }

    @Override
    public int hashCode() {
        return sessionKey.hashCode();
    }
}